#pragma once
#include <memory>
#include <string>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>

namespace hhfox
{
    using connection_hdl =  websocketpp::connection_hdl;
    using msg_type = websocketpp::frame::opcode::value;
    using Logger = std::function<void(int level, const std::string & file, int line, const std::string &msg)>;
    using connection_ptr = std::shared_ptr<websocketpp::connection<websocketpp::config::asio>>;
    enum class WebSocketEvent
    {
        Connected,
        Disconnected,
        Message
    };

    class IWebSocketHandler;
    class WebSocketServer;

    class IWebSocketHandler
    {
    public:
        IWebSocketHandler(WebSocketServer* server):server_(server){}
        virtual ~IWebSocketHandler(){}
        virtual void onOpen(connection_hdl hdl) = 0;
        virtual void onClose(connection_hdl hdl) = 0;
        virtual void onHttp(connection_hdl hdl) = 0;
        virtual void onMessage(connection_hdl hdl) = 0;
    protected:
        WebSocketServer* server_;
    };


    class WebSocketServerImpl;

    class WebSocketServer
    {
    public:
        WebSocketServer(const char *host, int port);

        ~WebSocketServer();

        void setLoggerCallback(Logger && logger);

        void start();

        void stop();

        void registerHandler(const std::string &uri, std::shared_ptr<IWebSocketHandler> handler);

        void sendRawMessage(websocketpp::connection_hdl hdl,void *buff, size_t len,msg_type op);
        
        void sendRawMessage(websocketpp::connection_hdl hdl,const std::string& msg);

        connection_ptr get_con_from_hdl(connection_hdl hdl);

    private:
        std::unique_ptr<WebSocketServerImpl> impl_;
    };
}